﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace RabbitMQDemo
{
    public partial class Routing : Form
    {
        private string exchangeName = "direct_logs";
        private string exchangeType = ExchangeType.Direct;//垂直交换机
        private readonly static Routing _Routing;
        Action<string, TextBox> SetText;
        static Routing()
        {
            _Routing = new Routing();
        }
        /// <summary>
        /// 单例模式
        /// </summary>
        public static Routing SingleForm { get { return _Routing; } }
        private Routing()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
            ReceiveMsg(txtConsumer1);
            ReceiveMsg(txtConsumer2);
            SetText += OnSetText;
        }

        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            SendMsg();
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        private void SendMsg()
        {
            string message = txtPublisher.Text;
            if (message.Trim().Length <= 0)
            {
                MessageBox.Show("请输入要发送的消息");
            }
            var factory = new ConnectionFactory() { HostName = "localhost" };
            using (var connection = factory.CreateConnection())
            using (var channel = connection.CreateModel())
            {
                channel.ExchangeDeclare(exchange: exchangeName,
                    type: exchangeType);

                var routingKey = cbBoxLevel.SelectedValue;

                var body = Encoding.UTF8.GetBytes(message);
                channel.BasicPublish(exchange: exchangeName,
                    routingKey: routingKey.ToString(),
                    basicProperties: null,
                    body: body);
            }
        }

        private void ReceiveMsg(TextBox box)
        {
            try
            {
                var factory = new ConnectionFactory() { HostName = "localhost" };
                var connection = factory.CreateConnection();
                var channel = connection.CreateModel();

                channel.ExchangeDeclare(exchange: exchangeName,
                    type: exchangeType);

                var queueName = channel.QueueDeclare().QueueName;

                if (box.Name == "txtConsumer1")
                {//消费者1能接受info和error的消息
                    channel.QueueBind(queue: queueName,
                        exchange: exchangeName,
                        routingKey: "info");
                    channel.QueueBind(queue: queueName,
                        exchange: exchangeName,
                        routingKey: "error");
                }
                else if (box.Name == "txtConsumer2")
                {//消费者2能接受debug和error的消息
                    channel.QueueBind(queue: queueName,
                        exchange: exchangeName,
                        routingKey: "debug");
                    channel.QueueBind(queue: queueName,
                        exchange: exchangeName,
                        routingKey: "error");
                }

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                  {
                      var msg = Encoding.UTF8.GetString(ea.Body);

                      box.Invoke(SetText, msg, box);
                  };

                channel.BasicConsume(queue: queueName,
                    noAck: true,
                    consumer: consumer);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        private void OnSetText(string text, TextBox box)
        {
            var split_Result = text.Split(':');
            if (split_Result.Length >= 2)
                text = split_Result[1];
            box.Text += string.Format("{0}\r\n", text);
        }

        private void Routing_Load(object sender, EventArgs e)
        {
            List<Receiver> lst = new List<Receiver>();
            lst.Add(new Receiver("消费者1", "info"));
            lst.Add(new Receiver("消费者2", "debug"));
            lst.Add(new Receiver("消费者1,消费者2", "error"));

            cbBoxLevel.DataSource = lst;
            cbBoxLevel.DisplayMember = "DisplayMember";
            cbBoxLevel.ValueMember = "ValueMember";
            cbBoxLevel.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        private class Receiver
        {
            public Receiver(string displayMember, string valueMember)
            {
                DisplayMember = displayMember;
                ValueMember = valueMember;
            }
            public string DisplayMember { get; set; }
            public string ValueMember { get; set; }
        }
    }
}
